• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /macosx-10.10.1/pyobjc-45/2.6/pyobjc/pyobjc-framework-Quartz/Examples/Programming with Quartz/BasicDrawing/
1from Quartz import *
2from Cocoa import *
3import Utilities
4import QuartzTextDrawing
5
6import sys
7import objc
8
9def getTextString():
10    # These unicode values are the characters: Q, u, a, r, t, z,
11    # eighthnote, floral heart, black chess queen, and two CJK characters.
12    # Note: Create an NSString, because we'll use NSString-specific API's, otherwise
13    # we could just have used a python unicode object
14    return NSString.stringWithString_(u'\u0051\u0075\u0061\u0072\u0074\u007A\u266A\u2766\u265B\u3042\u304E')
15
16doPointDrawing=1
17
18def drawNSStringWithAttributes():
19    textString = getTextString()
20    if doPointDrawing:
21        context = NSGraphicsContext.currentContext().graphicsPort()
22
23    # Text Line 1. Draw with default attributes.
24    p = NSMakePoint(20.0, 400.0)
25
26    # Draw text with default text attributes. The point supplied is
27    # not the text baseline but rather the lower-left corner of the box
28    # which bounds the text.
29    textString.drawAtPoint_withAttributes_(p, None)
30
31    if doPointDrawing:
32        Utilities.drawPoint(context, p)
33
34    # Text Line 2. Draw with a specific font and color.
35
36    # Position the text 50 units below the previous text.
37    p.y -= 50
38
39    # Set attributes to use when drawing the string.
40    stringAttributes = {
41        # Use the font with the PostScript name "Times-Roman" at 40 point.
42        NSFontAttributeName: NSFont.fontWithName_size_("Times-Roman", 40),
43
44        # Set the color attribute to an opaque red.
45        NSForegroundColorAttributeName: NSColor.colorWithCalibratedRed_green_blue_alpha_(0.663, 0, 0.031, 1.0)
46    }
47
48    # Draw the text.
49    textString.drawAtPoint_withAttributes_(p, stringAttributes)
50
51    if doPointDrawing:
52        Utilities.drawPoint(context, p)
53
54    # Text Line 3. Draw stroked text.
55
56    # Position the text 50 units below the previous text.
57    p.y -= 50
58
59    # Panther and later support stroke attributes. A positive value
60    # of the stroke width attribute produces text that is stroked rather
61    # than filled.
62    stringAttributes[NSStrokeWidthAttributeName] = 3.0
63    textString.drawAtPoint_withAttributes_(p, stringAttributes)
64
65    if doPointDrawing:
66        Utilities.drawPoint(context, p)
67
68    # Text Line 4. Draw with fill and stroke.
69
70    p.y -= 50
71
72    # Panther and later support stroke attributes. A negative value
73    # of the stroke width attribute results in text that is both filled
74    # and stroked.
75    stringAttributes[NSStrokeWidthAttributeName] = -3.0
76    # Set the stroke color attribute to black.
77    stringAttributes[NSStrokeColorAttributeName] = NSColor.colorWithCalibratedRed_green_blue_alpha_(0, 0, 0, 1.0)
78
79    textString.drawAtPoint_withAttributes_(p, stringAttributes)
80
81    if doPointDrawing:
82        Utilities.drawPoint(context, p)
83
84    # Text Line 5. Draw at baseline.
85    # Tiger and later support the drawWithRect method which allows
86    # string text drawing from a point on the text baseline.
87    p.y -= 50
88    rect = NSRect(
89            origin=p,
90            size=NSSize(0,0),
91        )
92    textString.drawWithRect_options_attributes_(
93            rect, NSStringDrawingDisableScreenFontSubstitution,
94            stringAttributes)
95
96    if doPointDrawing:
97        Utilities.drawPoint(context, p)
98
99_myLayout = None
100_textStorage = None
101_myTextRange = None
102def drawWithNSLayout():
103    global _myLayout, _textStorage, _myTextRange
104
105    if _myLayout is None:
106        # Initialize the text storage with the string to draw.
107        _textStorage = NSTextStorage.alloc().initWithString_(getTextString())
108        # Initialize the layout manager to use with the text storage.
109        _myLayout = NSLayoutManager.alloc().init()
110        # Allocate and initialize a text container object.
111        textContainer = NSTextContainer.alloc().init()
112        # Add the text container to the layout.
113        _myLayout.addTextContainer_(textContainer)
114        # Release the text container since the layout retains it and
115        # this code no longer needs it.
116        del textContainer
117        # Add the layout to the text storage.
118        _textStorage.addLayoutManager_(_myLayout)
119
120        # Set attributes to use when drawing the string.
121        stringAttributes = {
122            # Use the font with the PostScript name "Times-Roman" at 40 point.
123            NSFontAttributeName: NSFont.fontWithName_size_("Times-Roman", 40),
124
125            # Set the text color attribute to an opaque red.
126            NSForegroundColorAttributeName:  NSColor.colorWithCalibratedRed_green_blue_alpha_(0.663, 0, 0.031, 1.0),
127        }
128
129        # Create the range of text for the entire length of text
130        # in the textStorage object.
131        _myTextRange = NSMakeRange(0, _textStorage.length())
132        # Set the attributes on the entire range of text.
133        _textStorage.setAttributes_range_(stringAttributes, _myTextRange)
134
135    # Set the point for drawing the layout.
136    p = NSMakePoint(20.0, 400.0)
137
138    # Draw the text range at the point.
139    _myLayout.drawGlyphsForGlyphRange_atPoint_(_myTextRange, p)
140
141    if doPointDrawing:
142        context = NSGraphicsContext.currentContext().graphicsPort()
143        Utilities.drawPoint(context, p)
144
145# The interface to the NSLayoutManager subclass.
146class MyNSLayoutManager (NSLayoutManager):
147    # The extra instance variables for this subclass.
148    _textMode = objc.ivar()
149    _fColor = objc.ivar()
150    _sColor = objc.ivar()
151    _yStartPosition = objc.ivar()
152    _lineWidth = objc.ivar()
153    _clippingDrawProc = objc.ivar()
154    _clippingInfo = objc.ivar()
155
156    # Public methods to set the special attributes
157    # of the MyNSLayoutManager instance.
158    def setTextMode_(self, textMode):
159        self._textMode = textMode
160
161    def setFillColor_(self, color):
162        self._fColor = color
163
164    def setStrokeColor_(self, color):
165        self._sColor = color
166
167    def setTextLineWidth_(self, width):
168        self._lineWidth = width
169
170    def setClippingDrawProc_withInfo_(self, clippingDrawProc, info):
171	self._clippingDrawProc = clippingDrawProc
172	self._clippingInfo = info
173
174    def init(self):
175        self = super(MyNSLayoutManager, self).init()
176        if self is None:
177            return None
178
179
180        # Initialize the custom instance variables.
181        self._textMode = kCGTextFill
182        self._fColor = None
183        self._sColor = None
184        self._yStartPosition = 0
185        self._lineWidth = 1
186        self._clippingDrawProc = None
187        self._clippingInfo = None
188        return self
189
190    # This code overrides this method to record the y coordinate
191    # to use as the True baseline for the text drawing.
192    def drawGlyphsForGlyphRange_atPoint_(self, glyphsToShow, origin):
193        self._yStartPosition = origin.y
194        super(MyNSLayoutManager, self).drawGlyphsForGlyphRange_atPoint_(glyphsToShow, origin)
195
196    # This is the rendering method of NSLayoutManager that the
197    # code overrides to perform its custom rendering.
198    def showPackedGlyphs_length_glyphRange_atPoint_font_color_printAdjustment_(
199            self, glyphs, glyphLen, glyphRange, point, font, color, printingAdjustment):
200
201       # Obtain the destination drawing context.
202        context = NSGraphicsContext.currentContext().graphicsPort()
203
204        # Adjust start position y value based on the adjusted y coordinate.
205        # This ensures the text baseline is at the starting position
206        # passed to drawGlyphsForGlyphRange. This technique won't work
207        # for super, subscripts, or underlines but that's OK for this example.
208        point.y = _yStartPosition
209
210        # The Quartz graphics state should be preserved by showPackedGlyphs.
211        CGContextSaveGState(context)
212
213        # Set the desired text drawing mode.
214        CGContextSetTextDrawingMode(context, self._textMode)
215
216	# Set the fill color if needed.
217        if (self._textMode == kCGTextFill or _self.textMode == kCGTextFillStroke or
218                self._textMode == kCGTextFillClip or _textMode == kCGTextFillStrokeClip):
219            if self._fColor is not None:
220                CGContextSetFillColorWithColor(context, self._fColor)
221
222	# Set the  line width and the stroke color if needed.
223        if (self._textMode == kCGTextStroke or self._textMode == kCGTextFillStroke or
224                self._textMode == kCGTextStrokeClip or self._textMode == kCGTextFillStrokeClip):
225		CGContextSetLineWidth(context, self._lineWidth)
226                if self._sColor is not None:
227                    CGContextSetStrokeColorWithColor(context, self._sColor)
228
229	# Now draw the text. Check whether to adjust for printing widths
230        # and if needed adjust extra character spacing accordingly.
231        if printingAdjustment.width != 0.0:
232            # If printingAdjustment width is non-zero then the text
233            # needs to be adjusted. printingAdjustment is the per character
234            # adjustment required for this piece of text. Because
235            # the Quartz text character spacing set is transformed by
236            # the text matrix, this code needs to factor out that effect
237            # prior to setting it. Cocoa sets the text matrix to account
238            # for the point size of the font so we factor that out of the
239            # per character width supplied here.
240            charAdjust = printingAdjustment.width / font.pointSize()
241            CGContextSetCharacterSpacing(context, charAdjust)
242        else:
243            CGContextSetCharacterSpacing(context, 0.0)
244
245        # Draw the glyphs. The total number of glyphs is the length
246        # of the glyphs string passed to showPackedGlyphs, divided by 2
247        # since there are two bytes per glyph.
248        CGContextShowGlyphsAtPoint(context, point.x, point.y, glyphs, glyphLen/2)
249
250        # If the text drawing mode requires clipping and there is
251        # a custom clipping proc, call it. This allows drawing through
252        # clipped text before the graphics state is restored.
253        if (self._textMode == kCGTextClip or self._textMode == kCGTextFillClip or
254                self._textMode == kCGTextStrokeClip or
255                self._textMode == kCGTextFillStrokeClip) and self._clippingDrawProc is not None:
256
257		self._clippingDrawProc(context, point.x, point.y, self._clippingInfo)
258
259        CGContextRestoreGState(context)
260
261def MyClipProc(c, x, y, info):
262    CGContextTranslateCTM(c, x, y)
263    CGContextSetStrokeColorWithColor(c, Utilities.getRGBOpaqueBlackColor())
264    # Draw a grid of lines through the clip.
265    QuartzTextDrawing.drawGridLines(c);
266
267_myLayout = None
268_textStorage = None
269_myTextRange = None
270def drawWithCustomNSLayout():
271    global _myLayout, _textStorage, _myTextRange
272
273    if _myLayout is None:
274        textContainer = NSTextContainer.alloc().init()
275
276        _textStorage = NSTextStorage.alloc().initWithString_(getTextString())
277        # Create an instance of the MyNSLayoutManager subclass of NSLayoutManager.
278        _myLayout = MyNSLayoutManager.alloc().init()
279        _myLayout.addTextContainer_(textContainer)
280        # The layout retains the text container so this code can release it.
281        del textContainer
282        _textStorage.addLayoutManager_(_myLayout)
283
284        # Set attributes to use when drawing the string.
285        stringAttributes = {
286            # Use the font with the PostScript name "Times-Roman" at 40 point.
287            NSFontAttributeName: NSFont.fontWithName_size_("Times-Roman", 40),
288        }
289
290        # Create the range.
291        _myTextRange = NSMakeRange(0, _textStorage.length())
292        # Set the attributes on the entire range of text.
293        _textStorage.setAttributes_range_(stringAttributes, _myTextRange)
294
295    p = NSMakePoint(20.0, 400.0)
296
297    # Set the custom attributes of the layout subclass so that
298    # the text will be filled with black.
299    _myLayout.setTextMode_(kCGTextFill)
300    _myLayout.setFillColor_(Utilities.getRGBOpaqueBlackColor())
301
302    # Draw text line 1.
303    _myLayout.drawGlyphsForGlyphRange_atPoint_(_myTextRange, p)
304
305    if doPointDrawing:
306        context = NSGraphicsContext.currentContext().graphicsPort()
307        Utilities.drawPoint(context, p)
308
309    # Set the custom attributes of the layout subclass so that
310    # the text will be stroked with black.
311    _myLayout.setTextMode_(kCGTextStroke)
312    _myLayout.setStrokeColor_(Utilities.getRGBOpaqueBlackColor())
313    _myLayout.setTextLineWidth_(2)
314
315    # Draw text line 2.
316    p.y -= 50;
317    _myLayout.drawGlyphsForGlyphRange_atPoint_(_myTextRange, p)
318
319    if doPointDrawing:
320        Utilities.drawPoint(context, p)
321
322    p.y -= 50;
323
324    # Set the custom attributes of the layout subclass so that
325    # the text will be filled and stroked and the fill color
326    # will be red. Since the stroke color hasn't changed it
327    # will be stroked with black.
328    _myLayout.setTextMode_(kCGTextFillStroke)
329    _myLayout.setFillColor_(Utilities.getRGBOpaqueRedColor())
330    # Draw text line 3.
331    _myLayout.drawGlyphsForGlyphRange_atPoint_(_myTextRange, p)
332
333    if doPointDrawing:
334        Utilities.drawPoint(context, p)
335
336    p.y -= 50;
337
338    # Set the custom attributes of the layout subclass so that
339    # the text will be filled, stroked, then clipped.
340    _myLayout.setTextMode_(kCGTextFillStrokeClip)
341
342    # Set the clipping proc to MyClipProc which requires
343    # no info data.
344    _myLayout.setClippingDrawProc_withInfo_(MyClipProc, None)
345
346    # Draw text line 4.
347    _myLayout.drawGlyphsForGlyphRange_atPoint_(_myTextRange, p)
348
349    if doPointDrawing:
350        Utilities.drawPoint(context, p)
351
352    # Set the clipping proc to None for future drawing.
353    _myLayout.setClippingDrawProc_withInfo_(None, None)
354